/* 实现项目中的琐碎功能代码
    日志宏的实现
    json的序列化和反序列化
    uuid的生成
*/
#pragma once 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <memory>
#include <ctime>
#include <sstream>
#include <random>
#include <iomanip>
#include <string>
#include <atomic>
#include <jsoncpp/json/json.h>

namespace rpc
{
    #define LOG(LEVEL,format,...) do{\
        time_t t = time(NULL);\
        struct tm* st = localtime(&t);\
        char timebuffer[32] = {0};\
        memset(timebuffer,0,sizeof(timebuffer));\
        strftime(timebuffer,sizeof(timebuffer) - 1,"%m-%d-%T",st);\
        fprintf(stdout,"[%s][%s][%s:%d] " format "\n",LEVEL,timebuffer,__FILE__,__LINE__,##__VA_ARGS__);\
    }while(0)
    //##是一个标记连接符，当__VA_ARGS__为空时候，##会删除前面的逗号 
    #define DLOG(format,...) LOG("DEBUG",format,##__VA_ARGS__)
    #define ILOG(format,...) LOG("INFO",format,##__VA_ARGS__)
    #define ELOG(format,...) LOG("ERROR",format,##__VA_ARGS__)
    
    
    class JSON
    {
    public:
        static bool serialize(Json::Value stu,std::string& body)
        {
            std::stringstream ss;
            //实例化一个工厂类对象
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(stu,&ss);
    
            if(ret != 0)
            {
                ELOG("json serialize failed!");
                return false;
            }
            body = ss.str();
            return true;
        }
        static bool unserialize(const std::string& str,Json::Value& stu)
        {
            Json::CharReaderBuilder crb;
    
            std::string err;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret = cr->parse(str.c_str(),str.c_str() + str.size(),&stu,&err);
            if(ret == false)
            {
                ELOG("json unserialize failed : %s", err.c_str());
                return false;
            }
    
            return true;
        }
    };
    
    
    class UUID
    {
    public:
        static std::string uuid()
        {
            //rand周期长度短，随机数重复概率高，且随机数质量低，且不是线程安全的，所以不采用
            std::stringstream ss;
            //构造一个机器随机数对象
            std::random_device rd;
            //以机器数为种子构造随机数对象
            std::mt19937 generator(rd());
            //构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0,255);
            for(int i = 0;i < 8;i++)
            {
                if(i == 4 || i == 6) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";
            //定义一个8字节序号 
            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for(int i = 7;i >= 0;i--)
            {
                if(i == 5) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i*8)) & 0xFF);
            }
            return ss.str();
        }
    };
    
}